﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AzurePlugin.Converter;
using EnvDTE;

namespace AzurePlugin.WizardImpl
{
    public partial class frmWizard : Form
    {
        private const string BackupFolderName = "backup";

        public frmWizard()
        {
            InitializeComponent();
        }

        public Director director { get; set; }
        private string BackupFolder;
        private IEnumerable<Director.ProjectInfo> _projects;
        private IEnumerable<ProjectAdapter> _cloudProjects;

        private void rCreateBackupYes_CheckedChanged(object sender, EventArgs e)
        {
            bool createBackup = rCreateBackupYes.Checked;
            tbBackupDir.Enabled = bBackupBrowse.Enabled = createBackup;
        }

        private void doFinish()
        {
            new frmProgress().ShowProgress(
                    delegate()
                    {
                        try
                        {
                            if (rCreateBackupYes.Checked)
                                director.DoBackup(BackupFolder,
                                // to backup only selected to conversion projects
                                //    getProjectsToConversion().Select(i => i.ProjectAdapter.Project));
                                //
                                // to backup all (including non convertable) projects in solution
                                    director.GetAllProjects());

                            bool res = false;
                            switch (_cloudProjects.Count())
                            {
                                case 0:
                                    res = director.DoConversionNewProject(tbCloudProject.Text,
                                                                             getProjectsToConversion().Select(
                                                                                 i => i.ProjectAdapter));
                                    break;

                                case 1:
                                    res = director.DoConversionExistingProject((Project)_cloudProjects.First().Project,
                                                                               getProjectsToConversion().Select(
                                                                                   i => i.ProjectAdapter));
                                    break;

                                default:
                                    res = director.DoConversionExistingProject((Project) cbCloudProject.SelectedItem,
                                                                               getProjectsToConversion().Select(
                                                                                   i => i.ProjectAdapter));
                                    break;
                            }
                            if (res)
                            {
                                headerPageComplete.Title = "Conversion complete";
                                lPageComplete.Text =
                                    "Solution is converted successfully. Please the conversion log for complete information.";
                            }
                            else
                            {
                                headerPageComplete.Title = "Conversion failed";
                                lPageComplete.Text =
                                    "Conversion of solution is failed. Please the conversion log for complete information.";
                            }
                            wizard.NextTo(pageComplete);
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.Message, "Error during conversion");
                            wizard.NextTo(pageFailed);
                        }
                    });
        }

        private void bBackupBrowse_Click(object sender, EventArgs e)
        {
            fbdBackup.SelectedPath = tbBackupDir.Text;
            if (fbdBackup.ShowDialog() == DialogResult.OK)
            {
                tbBackupDir.Text = fbdBackup.SelectedPath;
            }
        }

        private void pageSummary_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            doFinish();
        }

        private void frmWizard_Shown(object sender, EventArgs e)
        {
            if (director.isSolutionOpen)
            {
                tbBackupDir.Text = director.solutionPath;
            }
            else
            {
                MessageBox.Show("Please open solution first");

                this.Close();
            }

            _projects = director.GetProjectsForConversion();
            _cloudProjects = director.GetAzureProjects();

            // select projects tab
            lvProjects.Items.Clear();
            foreach (var project in _projects)
            {
                var item = new ListViewItem(project.ProjectAdapter.Project.Name);
                item.Checked = true;
                item.Tag = project;
                item.SubItems.Add(
                    new ListViewItem.ListViewSubItem(
                        item, getConversionRoleName(project.ConversionType)));
                lvProjects.Items.Add(item);
            }

            // select cloud project tab
            if (_cloudProjects.Count() > 1)
            {
                cbCloudProject.Items.Clear();
                cbCloudProject.Items.AddRange(_cloudProjects.Select(i => i.Project).ToArray());
                cbCloudProject.DisplayMember = "Name";
                cbCloudProject.SelectedIndex = 0;
            }
            else
            {
                tbCloudProject.Text = director.cloudProjectNameByDefault;
            }

        }

        private void wizard_CloseFromCancel(object sender, CancelEventArgs e)
        {
            if (wizard.Page == pageComplete)
            {

                if (cbShowLog.Checked)
                    director.showLog();

            }

            e.Cancel = true;
        }

        private void pageBackup_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            for (int i = 1; i < Constants.OVER_9000; i++)
            {
                string suffix = i == 1 ? String.Empty : i.ToString();

                var folder = new DirectoryInfo(Path.Combine(tbBackupDir.Text, BackupFolderName + suffix));
                if (!folder.Exists)
                {
                    BackupFolder = folder.FullName;
                    return;
                }
            }

            // if there is already existed 9k backups
            MessageBox.Show(String.Format("Backups in '{0}' is full, please select different folder.",
                                          tbBackupDir.Text));

            e.Cancel = true;
        }

        private void pageSummary_ShowFromNext(object sender, EventArgs e)
        {
            var projects = getProjectsToConversion();

            var webProjects = from item in projects
                                 where item.ConversionType == Director.ConversionType.WebRole
                              select item.ProjectAdapter.Project.Name;

            var workerProjects = from item in projects
                                 where item.ConversionType == Director.ConversionType.WorkerRole
                                 select item.ProjectAdapter.Project.Name;

            int counter = 1;
            var summary = new List<string>();
            if (_cloudProjects.Count() == 0)
            {
                summary.Add(
                    String.Format(
                        "{0}) '{1}' Azure project will be added to the solution",
                        counter++,
                        tbCloudProject.Text
                        )
                    );
                summary.Add(String.Empty);
            }
 
            if (webProjects.Count() > 0)
            {
                summary.Add(
                    String.Format(
                        "{0}) {1} projects will be converted to Web Role projects",
                        counter++,
                        String.Join(", ", webProjects)
                        )
                    );
                summary.Add(String.Empty);
            }

            if (workerProjects.Count() > 0)
            {
                summary.Add(
                    String.Format(
                        "{0}) {1} projects will be converted to Worker Role projects",
                        counter++,
                        String.Join(", ", workerProjects)
                        )
                    );
                summary.Add(String.Empty);
            }

            taSummary.Lines = summary.ToArray();
        }

        private void pageSelectConversion_ShowFromNext(object sender, EventArgs e)
        {
        }

        private IEnumerable<Director.ProjectInfo> getProjectsToConversion()
        {
            return from ListViewItem item in lvProjects.Items
                      where item.Checked
                      select (Director.ProjectInfo) item.Tag;
        }

        private static string getConversionRoleName(Director.ConversionType type)
        {
            switch (type)
            {
                case Director.ConversionType.WebRole:
                    return "Web Role";
                case Director.ConversionType.WorkerRole:
                    return "Worker Role";
            }
            throw new ArgumentOutOfRangeException("ConversionType");
        }

        private void pageSelectCloud_ShowFromNext(object sender, EventArgs e)
        {

        }

        private void pageInfo_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            if (_projects.Count() == 0 && _cloudProjects.Count() > 0)
                e.Page = pageAlreadyConverted;
        }

        private void pageSelectConversion_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            switch (_cloudProjects.Count())
            {
                case 0:
                    e.Page = pageCloudName;
                    break;

                case 1:
                    e.Page = pageBackup;
                    break;

                default:
                    e.Page = pageSelectCloud;
                    break;
            }
        }

        private void pageCloudName_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            if (string.IsNullOrEmpty(tbCloudProject.Text))
            {
                MessageBox.Show(String.Format("Name of new Azure project should not be empty.",
                                              tbBackupDir.Text));

                e.Cancel = true;
                return;
            }
            else if (tbCloudProject.Text.EndsWith("."))
            {
                MessageBox.Show(String.Format("Name of new Azure project should not end with '.' character.",
                                              tbBackupDir.Text));

                e.Cancel = true;
                return;
            }
            else if (director.doesProjectExist(tbCloudProject.Text))
            {
                MessageBox.Show(String.Format("Project '{0}' already exist in solution, please select different name.",
                                              tbCloudProject.Text));

                e.Cancel = true;
                return;
            }

            e.Page = pageBackup;
        }

        private void pageSelectCloud_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
           e.Page = pageBackup;
        }

        private void pageSelectCloud_CloseFromBack(object sender, Gui.Wizard.PageEventArgs e)
        {
            e.Page = pageSelectConversion;
        }

        private void pageBackup_CloseFromBack(object sender, Gui.Wizard.PageEventArgs e)
        {
            switch (_cloudProjects.Count())
            {
                case 0:
                   e.Page = pageCloudName;
                    break;

                case 1:
                    e.Page = pageInfo;
                    break;

                default:
                    e.Page = pageSelectCloud;
                    break;
            }
        }
    }
}
